from DataParser import getDataAndDivide
from DataParser import getData
from Example import Example 
from Drawer import Drawer

def matches(detector, list, min_dist):
    for i in list:
        dist = detector.euclidean(i)
        if dist <= min_dist:
            return True
    return False

def generate_detectors(max_detectors, min_dist, bounds, data):
    detectors = []
    while len(detectors) < max_detectors:
        detector = Example.create_random(bounds,4)
        if not matches(detector, data, min_dist):
            if not matches(detector, detectors, 0.0):
                detectors.append(detector)
                if(len(detectors) % 100 == 0):
                    print len(detectors)
    return detectors

def classify(example_to_classify, detectors_map, min_dist):
    classes = []
    for key in detectors_map.keys():
        if not matches(example_to_classify, detectors_map[key], min_dist):
            example_to_classify.label = key
            classes.append(key)
    return classes

def run(max_detectors, min_dist, bounds, file_name):
    print "reading data set"
    (data_trening, data_test) = getDataAndDivide(file_name) 
    detectors_map = {}
    for key in data_trening.keys():
        print "generating detectors for " + key
        detectors_map[key] = generate_detectors(max_detectors, min_dist, bounds, data_trening[key])
    print "testing...\n"
    print "classified | should be"
    correct = 0
    for key in data_test:
        for example in data_test[key]:
            classes = classify(example, detectors_map, min_dist)
            print ','.join(classes) + "|" + key
            if len(classes) == 1 and classes[0] == key:
                correct = correct + 1
    
    print "correct: " + str(correct)
    all = reduce(lambda x, y: x + len(data_test[y]), data_test,0)
    print "effectiveness: " + str(correct / float(all))
           
def run_spirala(max_detectors, min_dist, bounds, training_file_name, test_file_name):
    print "reading data set"
    data_trening = getData(training_file_name) 
    detectors_map = {}
    for key in data_trening.keys():
        print "generating detectors for " + key
        detectors_map[key] = generate_detectors(max_detectors, min_dist, bounds, data_trening[key])
    print "testing...\n"
    test_examples = getData(test_file_name).values()[0]
    results = []
    for test_example in test_examples:
        classes = classify(test_example, detectors_map, min_dist)
        results.append(len(classes) == 1) #if classes = [Spiral]
    x_points_spiral = []
    y_points_spiral = []
    x_points_not_spiral = []
    y_points_not_spiral = []
    for (example, result) in zip(test_examples,results):
        if result:
            x_points_spiral.append(example.attrs[0])
            y_points_spiral.append(example.attrs[1])
        else:
            x_points_not_spiral.append(example.attrs[0])
            y_points_not_spiral.append(example.attrs[1])    
    drawer = Drawer()
    drawer.plot(x_points_spiral, y_points_spiral, "go")
    drawer.plot(x_points_not_spiral, y_points_not_spiral, "ro")
    drawer.draw()
    raw_input()
    
if __name__ == '__main__':
    '''
    irysy
    '''
#    max_detectors = 500
#    min_dist = 6 #align in experiment
#    bounds = (0.1, 8.0)
#    file_name ="iris.data"
#    run(max_detectors, min_dist, bounds, file_name)
    '''
    spirala
    '''
    max_detectors = 3000
    min_dist = 0.03
    bounds = (-1,1)
    training_file_name = "spirala.data"
    test_file_name = "spirala_test.data"
    run_spirala(max_detectors, min_dist, bounds, training_file_name,test_file_name)